import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Function;
import file.FileRead;
import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.DecimalFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.jexl.Expression;
import org.apache.commons.jexl.ExpressionFactory;
import org.apache.commons.jexl.JexlContext;
import org.apache.commons.jexl.context.HashMapContext;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.client.utils.URIBuilder;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.util.CollectionUtils;
import org.xhtmlrenderer.css.parser.property.PrimitivePropertyBuilders.Page;

/**
 * Created by wuzhao on 2016/12/29 0029.
 */
public class Test {

  public static void main(String[] args) throws Exception {
    String signkey = "DEV_SIGN_KEY@YGMG";
    String digestKey = "DEV_DIGEST_KEY@YGMG";

    String md5Signkey = DigestUtils.md5Hex(signkey);
    String md5DigestKey = DigestUtils.md5Hex(digestKey);
    System.out.printf("signkey:"+md5Signkey);
    System.out.printf("digestKey:"+md5DigestKey);

  }

  public static void jexl() {
    //1.创建jexl
    Expression exp = null;
    try {
      exp = ExpressionFactory.createExpression("i/j+j");
    } catch (Exception e) {
      e.printStackTrace();
    }

    // 2.做一个jexlContext并把它放入其中, MapConext类clear方法可以清空set过的值
    JexlContext jc = new HashMapContext();

    // 3.设置变量的值,这个值可以在执行的表达式中调用
    Map jexlContextMap = new HashMap();
    jexlContextMap.put("i", new BigDecimal("7"));
    jexlContextMap.put("j", new BigDecimal("3"));

    jc.setVars(jexlContextMap);

    // 5.执行并返回结果
    Object evaluate = null;
    try {
      evaluate = exp.evaluate(jc);
    } catch (Exception e) {
      e.printStackTrace();
    }
    String evaluateStr = evaluate.toString();
    BigDecimal bigDecimal = new BigDecimal(evaluateStr);
    bigDecimal = bigDecimal.multiply(BigDecimal.ONE).setScale(2, RoundingMode.HALF_UP);
    System.out.printf("===" + bigDecimal.toString());
  }

  //字符串分割为数组
  public static void splitToList() {
    String perms = "sys:base:query,sys:crmbatch:all,sys:crmbatch:test,sys:crmbatchroom:all";
    List<String> strings = Arrays.asList(perms.trim().split(","));
    System.out.printf("===" + strings);
  }

  public static int getStepNum(int number, int stepCount) {
    if (number <= 0 || stepCount <= 0) {
      return 0;
    }

    int divisor = number / stepCount;
    int residue = number % stepCount;
    return divisor + (residue > 0 ? 1 : 0);
  }

  private static <T> void test1(T users, Function<T, String> getId) {
    String apply = getId.apply(users);
    System.out.printf("===" + apply);
  }

  public static long backHomeLeft() {
    long leftMin = 0;
    int backHomeHour = 17;
    int backHomeMin = 30;
    LocalDateTime nowDateTime = LocalDateTime.now();
    int nowYear = nowDateTime.getYear();
    int nowMonth = nowDateTime.getMonthValue();
    int nowDay = nowDateTime.getDayOfMonth();
    LocalDateTime backHomeTime = LocalDateTime
        .of(nowYear, nowMonth, nowDay, backHomeHour, backHomeMin);

    long year = ChronoUnit.YEARS.between(nowDateTime, backHomeTime);
    long month = ChronoUnit.MONTHS.between(nowDateTime, backHomeTime);
    long days = ChronoUnit.DAYS.between(nowDateTime, backHomeTime);
    leftMin = ChronoUnit.MINUTES.between(nowDateTime, backHomeTime);
    return leftMin;
  }

  public static BigDecimal readStrAsBigDecimalAndCheckFormat(String str) {
    try {
      DecimalFormat format = new DecimalFormat();
      format.setParseBigDecimal(true);
      ParsePosition position = new ParsePosition(0);
      BigDecimal parse = (BigDecimal) format.parse(str, position);

      if (str.length() == position.getIndex()) {
        return parse;
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  public static String convertToLower(String str) {
    str = str.trim().toLowerCase().replace(" ", "_");
    return str;
  }

  public static String getTimePeriod(Date start1, Date start2, Date end1, Date end2) {
    Date start = start1.getTime() > end1.getTime() ? start1 : end1;
    Date end = start2.getTime() > end2.getTime() ? end2 : start2;
    BigDecimal diff = new BigDecimal(end.getTime() - start.getTime());
    return diff.compareTo(BigDecimal.ZERO) > 0 ? "" + diff
        .divide(new BigDecimal(24 * 3600 * 1000), RoundingMode.UP) : "无交集";
  }

  /**
   * 计算两个日期的相差天数(d1-d2)
   */
  public static String getDayDifference(Date d1, Date d2) {
    StringBuffer ds = new StringBuffer();
    try {
      long num = (d1.getTime() - d2.getTime()) / 1000;
      long days = num / (3600 * 24);
      if (days > 0) {
        ds.append(days);
      }
    } catch (Exception e) {
      ds = new StringBuffer("");
      e.printStackTrace();
    }
    return ds.toString();
  }


  /**
   * 这里共有2个时间段（b1-----e1）【b2-----e2】，4个时间点； 相当于两条线段(b代表起点，e代表端点，b<=e)，4个端点。 可分3种情况：
   * 1.不相交。（b1-----e1）【b2-----e2】（b1-----e1）。if(e1<b2||b1>e2)此时，重合天数为零。 2.相交。
   * 情况一：（b1---【b2---e1）----e2】          if(b1<b2&&e1<e2&&e1>b2) 情况二：【b2---(b1---e2】----e1)
   * if(b1>b2&&b1<e2&&e2<e1) 3.包含：计算较短的时间段日期长度。 （b1---【b2-----e2】--e1）			   if(b1<b2&&e1>e2)
   * 【b2---（b1-----e1）--e2】			   if(b1>b2&&e1<e2)
   *
   * @param begindate1 开始日期
   * @param enddate1   结束日期
   * @param begindate2 开始日期
   * @param enddate2   结束日期
   */
  public static String getDayCoincidence(Date begindate1, Date enddate1, Date begindate2,
      Date enddate2) {
    long b1 = begindate1.getTime();
    long e1 = enddate1.getTime();
    long b2 = begindate2.getTime();
    long e2 = enddate2.getTime();
    assert (b1 < e1 && b2 < e2);
    String coincidenceday;
    if (b1 <= b2 && e1 >= e2) {
      //（b1---【b2-----e2】--e1）
      System.out.println("1包含2");
      coincidenceday = getDayDifference(enddate2, begindate2);
    } else if (b1 >= b2 && e1 <= e2) {
      //【b2---（b1-----e1）--e2】
      System.out.println("2包含1");
      coincidenceday = getDayDifference(enddate1, begindate1);
    } else if (b1 >= b2 && b1 <= e2 && e2 <= e1) {
      //【b2---(b1---e2】----e1)
      System.out.println("相交");
      coincidenceday = getDayDifference(enddate2, begindate1);
    } else if (b1 <= b2 && e1 <= e2 && e1 >= b2) {
      //（b1---【b2---e1）----e2】
      System.out.println("相交");
      coincidenceday = getDayDifference(enddate1, begindate2);
    } else if (e1 <= b2 || b1 >= e2) {
      coincidenceday = "0";
    } else {
      coincidenceday = "";
      System.out.println("意料外的日期组合，无法计算重合天数！");
    }
    System.out.println("重合天数为[" + coincidenceday + "]天。");
    return coincidenceday;
  }

  public static String getCharset(String fileName) throws IOException {

    BufferedInputStream bin = new BufferedInputStream(new FileInputStream(fileName));
    int p = (bin.read() << 8) + bin.read();

    String code = null;

    switch (p) {
      case 0xefbb:
        code = "UTF-8";
        break;
      case 0xfffe:
        code = "Unicode";
        break;
      case 0xfeff:
        code = "UTF-16BE";
        break;
      default:
        code = "GBK";
    }
    return code;
  }


  private static String createAssignFile() {
    String fileName = assemblyFileName();
    File fileF = new File("/home/wasadmin/");
    File file = new File("/home/wasadmin/" + fileName);
    try {
      fileF.mkdirs();
      file.createNewFile();
    } catch (Exception e) {
      e.printStackTrace();
    }
    StringBuffer firstLine = new StringBuffer();
    firstLine.append("" + "size" + "|" + "orderAmount" + "|" + "depositoryId" + "|");
    List<StringBuffer> secondLineList = fillSecondLine();

    BufferedWriter bw = null;
    FileWriter fw = null;
    try {
      fw = new FileWriter(file, false);
      bw = new BufferedWriter(fw);
      bw.write(firstLine.toString());
      bw.newLine();
      for (StringBuffer sb : secondLineList) {
        bw.write(sb.toString());
        bw.newLine();
      }

    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (bw != null) {
          bw.close();
        }
        if (fw != null) {
          fw.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    return fileName;
  }

  private static List<StringBuffer> fillSecondLine() {

    List<StringBuffer> entityList = new ArrayList<>();
    for (int i = 0; i < 3; i++) {

      StringBuffer sb = new StringBuffer();
      sb.append(getFixLenthString(10) + "|");
      sb.append("investAmt" + "|");
      sb.append("1" + "&");
      sb.append("InvestDetailId" + "&");
      sb.append("LoanId" + "&");
      sb.append("BusinessNo" + "&");
      sb.append("DepositoryId" + "&");
      sb.append("RealName" + "&");
      sb.append("InvestAmt" + "&");
      sb.append("InvestAmt" + "&");
      sb.append("0" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      sb.append("tenor" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      sb.append("" + "&");
      entityList.add(sb);
    }
    return entityList;
  }

  private static String assemblyFileName() {
    SimpleDateFormat tempDate = new SimpleDateFormat("yyMMdd");
    String datetime = tempDate.format(new java.util.Date());
    String randomNum = getFixLenthString(10);
    String no = "BAT-6007-5424" + "-" + datetime + "-" + randomNum + "-" + "REQ" + ".txt";
    return no;
  }

  private static String getFixLenthString(int strLength) {

    Random rm = new Random();

    // 获得随机数
    double pross = (1 + rm.nextDouble()) * Math.pow(10, strLength);

    // 将获得的获得随机数转化为字符串
    String fixLenthString = String.valueOf(pross);

    // 返回固定的长度的随机数
    return fixLenthString.substring(2, strLength + 1);
  }

  public static Integer accuracy(BigDecimal dividend, BigDecimal divisor) {
    if (dividend == null || divisor == null || dividend.compareTo(BigDecimal.ZERO) == 0) {
      return 0;
    }
    BigDecimal divide = dividend.divide(divisor, 2, RoundingMode.HALF_UP);
    BigDecimal accuracyNum = divide.multiply(BigDecimal
        .valueOf(100));
    return accuracyNum.intValue();
  }

  public static int randomPercentage() {
    double d = Math.random() * 100;
    if ((d -= 30) < 0) {
      return 1;
    }
    if ((d -= 12) < 0) {
      return 2;
    }
    if ((d -= 45) < 0) {
      return 3;
    }
    return 4;
  }

  public static void exportExcel() throws IOException {

    //完整数据
    String targetJson = FileRead
        .readTxt("C:\\Users\\Administrator\\Desktop\\temp3\\temp\\city\\target.json");
    JSONArray targetJsonArray = JSON.parseArray(targetJson);
    Iterator<Object> targetIterator = targetJsonArray.iterator();

    //数据库中的数据
    String sourceJson = FileRead
        .readTxt("C:\\Users\\Administrator\\Desktop\\temp3\\temp\\city\\source.json");
    JSONObject sourceJsonObject = JSON.parseObject(sourceJson);
    JSONArray records = sourceJsonObject.getJSONArray("RECORDS");

    HSSFWorkbook workbook = new HSSFWorkbook();
    HSSFSheet sheet = workbook.createSheet("dictionary");

    int cellCount = 0;
    Long newPrPId = 2140011351244901114L;//省的父级ID

    while (targetIterator.hasNext()) {//循环完整数据的省
      JSONObject targetNext = (JSONObject) targetIterator.next();
      String targetProvinceName = targetNext.getString("name");
      JSONArray targetCity = targetNext.getJSONArray("city");

      Iterator<Object> sourceIterator = records.iterator();
      while (sourceIterator.hasNext()) {//循环原数据的省
        JSONObject sourceNext = (JSONObject) sourceIterator.next();
        String sourceName = sourceNext.getString("name");
        String[] gnames = sourceNext.getString("gname").split(",");//数据库中存在的城市

        Long newParentId = sourceNext.getLong("id");
        if (targetProvinceName.equals("新疆")) {
          System.out.println("===");
        }
        if (targetProvinceName.equals(sourceName)) {//匹配到省

          Iterator<Object> targetCityIterator = targetCity.iterator();
          while (targetCityIterator.hasNext()) {//遍历城市
            String newName;

            JSONObject targetCityNext = (JSONObject) targetCityIterator.next();
            newName = targetCityNext.getString("name");

            boolean isExist = false;
            for (int i = 0; i < gnames.length; i++) {
              if (gnames[i].equals(newName)) {
                isExist = true;
              }
            }
            if (isExist) {
              System.out.println("===" + "城市已经存在");
              continue;
            }
            dealRow(sheet, System.nanoTime(), cellCount, newName, newParentId, 2);//新增行
            cellCount++;

          }
          targetIterator.remove();//处理过的就移除掉
          break;
        }
      }
    }

    if (!CollectionUtils.isEmpty(targetJsonArray)) {//没有匹配的省
      Iterator<Object> iterator = targetJsonArray.iterator();
      while (iterator.hasNext()) {//循环完整数据的省
        JSONObject targetNext = (JSONObject) iterator.next();
        String targetProvinceName = targetNext.getString("name");
        JSONArray targetCity = targetNext.getJSONArray("city");
        Long prId = System.nanoTime();
        //新增省列
        dealRow(sheet, prId, cellCount, targetProvinceName, newPrPId, 1);
        cellCount++;
        Iterator<Object> targetCityIterator = targetCity.iterator();
        while (targetCityIterator.hasNext()) {//遍历城市
          String newName;
          JSONObject targetCityNext = (JSONObject) targetCityIterator.next();
          newName = targetCityNext.getString("name");
          dealRow(sheet, System.nanoTime(), cellCount, newName, prId, 2);//新增行
          cellCount++;
        }
      }

    }
    File excelFile = new File("C:\\Users\\Administrator\\Desktop\\temp3\\temp\\city\\date.xls");
    if (!excelFile.exists()) {
      excelFile.createNewFile();
    }
    FileOutputStream out = new FileOutputStream(excelFile);
    workbook.write(out);

  }

  public static void dealRow(HSSFSheet sheet, Long id, int cellCount, String newName,
      Long newParentId, int newLevel) {
    HSSFRow row = sheet.createRow(cellCount);
    row.createCell(0).setCellValue("" + id);//id
    row.createCell(1).setCellValue(1);//active_state
    row.createCell(2).setCellValue(newName);//name
    row.createCell(3).setCellValue("district");//type
    row.createCell(4).setCellValue(0);//display_order
    row.createCell(5).setCellValue("自动生成");//description
    row.createCell(6).setCellValue("" + newParentId);//parent_id
    row.createCell(7).setCellValue(newLevel);//level
    row.createCell(8).setCellValue(1);//state
    row.createCell(9).setCellValue(new Date());//updated_at
    row.createCell(10).setCellValue(new Date());//created_at
    row.createCell(11).setCellValue("");//others
    row.createCell(12).setCellValue(2);//is_online
    row.createCell(13).setCellValue("");//img_url
  }

  public static void synchronizedTest(List<String> tagNames, List<String> userAccounts) {
    String sysStr = (tagNames.toString() + "=" + userAccounts.toString()).intern();
    synchronized (sysStr) {
      System.out.println("===" + sysStr);
      try {
        Thread.sleep(3000L);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("===结束" + sysStr);
  }

  public static String getQueryString(String key, String queryString) {
    String[] pairs = queryString.split("&");
    for (String pair : pairs) {
      int idx = pair.indexOf("=");
      String key_pair = pair.substring(0, idx);
      if (key_pair.equals(key)) {
        return pair.substring(idx + 1);
      }
    }
    return null;
  }

  public static void filter() {
    Date date = DateUtils.addMinutes(new Date(), 30);
    Date end = DateUtils.addHours(new Date(), 1);
    System.out.printf("===" + end.after(date));
  }

  public static void reg() {
    Pattern patternAndroid = Pattern.compile("^[A_].*$");
    Matcher matcher = patternAndroid.matcher("A_mi_00b8b16aa66a95a1b152bdd9a2aea56e");
    System.out.println(matcher.matches());
  }

  public static String getRandomString(int length) { //length表示生成字符串的长度
    String base = "abcdefghijklmnopqrstuvwxyz0123456789";
    Random random = new Random();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < length; i++) {
      int number = random.nextInt(base.length());
      sb.append(base.charAt(number));
    }
    return sb.toString();
  }

  public static Long hash(String key) {
    ByteBuffer buf = ByteBuffer.wrap(key.getBytes());
    int seed = 0x1234ABCD;

    ByteOrder byteOrder = buf.order();
    buf.order(ByteOrder.LITTLE_ENDIAN);

    long m = 0xc6a4a7935bd1e995L;
    int r = 47;

    long h = seed ^ (buf.remaining() * m);

    long k;
    while (buf.remaining() >= 8) {
      k = buf.getLong();

      k *= m;
      k ^= k >>> r;
      k *= m;

      h ^= k;
      h *= m;
    }

    if (buf.remaining() > 0) {
      ByteBuffer finish = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);
      // for big-endian version, do this first:
      // finish.position(8-buf.remaining());
      finish.put(buf).rewind();
      h ^= finish.getLong();
      h *= m;
    }

    h ^= h >>> r;
    h *= m;
    h ^= h >>> r;

    buf.order(byteOrder);
    return h;
  }

  public static void testHash() {
    HashMap<Integer, LinkedList<String>> map = new HashMap<Integer, LinkedList<String>>();
    LinkedList<String> list1 = new LinkedList<String>();
    LinkedList<String> list2 = new LinkedList<String>();
    LinkedList<String> list3 = new LinkedList<String>();
    map.put(0, list1);
    map.put(1, list2);
    map.put(2, list3);
    for (int i = 0; i < 1000; i++) {
      String random = getRandom();
      int hashCode = random.hashCode();
      int index = hashCode % 3;
      LinkedList<String> linkedList = map.get(index);
      linkedList.add(random);
    }
    System.out.println(list1.size() + "==" + list2.size() + "==" + list3.size());
  }

  public static String getRandom() {
    int randomNum = (int) (Math.random() * 100000);
    String str = String.format("%06d", randomNum);
    return str;
  }
}
